package org.jing.r18.game.comm.kirikiri;

import org.jing.core.lang.ExceptionHandler;
import org.jing.core.lang.JingException;
import org.jing.core.logger.JingLogger;
import org.jing.r18.game.venusblood.util.Helper;

import java.util.zip.Deflater;

/**
 * Description: <br>
 *
 * @author: bks <br>
 * @createDate: 2025-04-16 <br>
 */
@SuppressWarnings({ "DuplicatedCode", "CommentedOutCode", "unused" })
public class KiriKiriHelper {
    private static final JingLogger LOGGER = JingLogger.getLogger(KiriKiriHelper.class);

    public static KiriKiriKsdFile decodeKsdFile(byte[] allBytes) {
        ExceptionHandler.publishIfMatch(allBytes[0] != -2 || allBytes[1] != -2 || allBytes[3] != -1 || allBytes[4] != -2, "Not a scrambled KiriKiri file.");
        byte model = allBytes[2];
        KiriKiriKsdFile file = new KiriKiriKsdFile();
        file.setModel(model);

        // 根据模式选择解压方式
        String content;
        switch (file.getModel()) {
            case 0: {
                file.setBuffer(decompressKsd0(allBytes));
                break;
            }
            case 1: {
                file.setBuffer(decompressKsd1(allBytes));
                break;
            }
            case 2: {
                file.setBuffer(decompressKsd2(allBytes));
                break;
            }
            default: throw new JingException("invalid model: [{}]", model);
        }
        LOGGER.info("解析完成: [{}]", file);
        return file;
    }

    private static byte[] decompressKsd0(byte[] allBytes) {
        /*
        byte[] data = reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position));
        for (int i = 0; i < data.Length; i += 2)
        {
            if (data[i + 1] == 0 && data[i] < 0x20)
                continue;

            data[i + 1] ^= (byte)(data[i] & 0xFE);
            data[i] ^= 1;
        }
        return data;
         */
        throw new JingException("模式[{}]暂不支持", 0);
    }

    private static byte[] decompressKsd1(byte[] allBytes) {
        /*
        byte[] data = reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position));
        for (int i = 0; i < data.Length; i += 2)
        {
            char c = (char)(data[i] | (data[i + 1] << 8));
            c = (char)(((c & 0xAAAA) >> 1) | ((c & 0x5555) << 1));
            data[i] = (byte)c;
            data[i + 1] = (byte)(c >> 8);
        }
        return data;
         */
        throw new JingException("模式[{}]暂不支持", 1);
    }

    private static byte[] decompressKsd2(byte[] allBytes) {
        long compressedLength = Helper.byteArrayToLong(allBytes, 5);
        long uncompressedLength = Helper.byteArrayToLong(allBytes, 13);
        LOGGER.info("文件解包: [compressedLength: {}][uncompressedLength: {}]", compressedLength, uncompressedLength);
        // 2 + 1 + 2 + 8 + 8
        final int usedLength = 21;
        byte[] compressedData = new byte[allBytes.length - usedLength];
        System.arraycopy(allBytes, usedLength, compressedData, 0, compressedData.length);
        return Helper.inflate(compressedData, false);
    }

    public static byte[] encodeKsdFile(String content, byte model) {
        KiriKiriKsdFile file = new KiriKiriKsdFile();
        file.setModel(model);
        file.setContent(content);
        return encodeKsdFile(file);
    }

    public static byte[] encodeKsdFile(KiriKiriKsdFile file) {
        LOGGER.info("处理文件: [{}]", file);
        // 根据模式选择压缩方式
        byte[] buffer;
        switch (file.getModel()) {
            case 0: {
                buffer = compressKsd0(file);
                break;
            }
            case 1: {
                buffer = compressKsd1(file);
                break;
            }
            case 2: {
                buffer = compressKsd2(file);
                break;
            }
            default: throw new JingException("invalid model: [{}]", file.getModel());
        }
        return buffer;
    }

    private static byte[] compressKsd0(KiriKiriKsdFile file) {
        throw new JingException("模式[{}]暂不支持", file.getModel());
    }

    private static byte[] compressKsd1(KiriKiriKsdFile file) {
        throw new JingException("模式[{}]暂不支持", file.getModel());
    }

    private static byte[] compressKsd2(KiriKiriKsdFile file) {
        byte[] uncompressedData = file.getBuffer();
        byte[] compressedData = Helper.deflate(uncompressedData, Deflater.DEFAULT_COMPRESSION, false);
        LOGGER.info("文件打包: [compressedLength: {}][uncompressedLength: {}]", compressedData.length, uncompressedData.length);
        // 2 + 1 + 2 + 8 + 8
        final int usedLength = 21;
        byte[] buffer = new byte[usedLength + compressedData.length];
        buffer[0] = -2;
        buffer[1] = -2;
        buffer[2] = 2;
        buffer[3] = -1;
        buffer[4] = -2;
        Helper.longToByteArray(compressedData.length, buffer, 5);
        Helper.longToByteArray(uncompressedData.length, buffer, 13);
        System.arraycopy(compressedData, 0, buffer, usedLength, compressedData.length);
        LOGGER.info("长度: [{}]", buffer.length);
        return buffer;
    }
}
